package com.ship.dispatch.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ship.common.business.service.impl.BaseServiceImpl;
import com.ship.common.core.base.Page;
import com.ship.common.core.domain.R;
import com.ship.common.core.exception.BusException;
import com.ship.common.core.utils.BeanCopyUtils;
import com.ship.common.core.web.domain.BaseResultCode;
import com.ship.common.core.web.domain.JsonResult;
import com.ship.common.security.utils.SecurityUtils;
import com.ship.dispatch.bean.*;
import com.ship.dispatch.bo.HistoryDispatchBO;
import com.ship.dispatch.bo.ShipRentYearInfoBO;
import com.ship.dispatch.mapper.*;
import com.ship.dispatch.model.Vo.SpArrangeDataVo;
import com.ship.dispatch.model.dto.SchemeChartSellDto;
import com.ship.dispatch.model.dto.SchemeChartSimpleDto;
import com.ship.dispatch.service.*;
import com.ship.dispatch.util.CommonUtil;
import com.ship.dispatch.util.NumberFormatUtil;
import com.ship.dispatch.vo.SpDispatchSchemeDetailExVo;
import com.ship.system.api.RemoteFileService;
import com.ship.system.api.domain.SysFile;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.net.URLConnection;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 * 年度计划 服务实现类
 * </p>
 *
 * @author AbyssRabbit@163.com
 * @since 2023-10-17
 */
@Service
@Slf4j
public class SpDispatchPotentialServiceImpl extends BaseServiceImpl<SpDispatchPotentialSchemeMapper, SpDispatchPotentialScheme>
        implements SpDispatchPotentialService {

    @Autowired
    @Lazy
    private SpInformationService spInformationService;

    @Autowired
    @Lazy
    private SpDispatchPotentialSchemeDetailService spDispatchSchemeDetailService;

    @Autowired
    private ConShippingService conShippingService;

    @Autowired(required = false)
    private ConResourceMemorandumMapper resourceMemorandumMapper;

    @Resource
    private RemoteFileService remoteFileService;

    @Override
    public JsonResult getPlanSchemeChart(SchemeChartSimpleDto dto) {
        //获取船舶信息
        List<SpInformation> spInformations = spInformationService.getAllSpInformationUsedPotential();
        BigDecimal shipUseRate = BigDecimal.ZERO;
        BigDecimal dispatchCost = BigDecimal.ZERO;
        JSONObject emptyResultData = new JSONObject();
        JSONArray emptyBoatsArray = new JSONArray();
        if(spInformations.size() == 0){
            return JsonResult.success(emptyResultData);
        }
        for (SpInformation spInformation : spInformations) {
            String boatName = spInformation.getNameOfVessel();
            if(boatName.indexOf("虚拟") > -1){
                continue;
            }
            JSONObject boatDetailJson = new JSONObject();
            boatDetailJson.put("imo",spInformation.getImo());
            boatDetailJson.put("storageCapacity",spInformation.getStorageCapacity());
            boatDetailJson.put("storageCapacityMmbtu",spInformation.getStorageCapacityMmbtu());
            boatDetailJson.put("rentTimeSlot",JSONArray.parseArray(spInformation.getRentTimeSlot()));
            boatDetailJson.put("shipName",boatName);
            boatDetailJson.put("details",new LinkedList<>());
            emptyBoatsArray.add(boatDetailJson);
        }
        emptyResultData.put("tradingProfit",0.00);
        emptyResultData.put("unoccupiedDays",0);
        emptyResultData.put("shipUseRate",shipUseRate);
        emptyResultData.put("dispatchCost",dispatchCost);
        emptyResultData.put("shipNames",emptyBoatsArray);
        emptyResultData.put("planId",dto.getPlanId());
        emptyResultData.put("goodsNames",new JSONArray());
        emptyResultData.put("sellerNames",new JSONArray());

        //获取最新的方案
        SpDispatchPotentialScheme spDispatchSchemes = this.baseMapper.selectOne(
                new LambdaQueryWrapper<SpDispatchPotentialScheme>()
                        .eq(StringUtils.isNotBlank(dto.getSchemeId()),SpDispatchPotentialScheme::getId,dto.getSchemeId())
                        .eq(SpDispatchPotentialScheme::getIsHistory,0)
                        .and(qw -> {
                            qw.eq(SpDispatchPotentialScheme::getCreateBy,SecurityUtils.getUsername());
                            qw.or().eq(SpDispatchPotentialScheme::getIsShare,1);
                        })
                        .orderByDesc(SpDispatchPotentialScheme::getCreateDate)
                        .last("limit 1")
        );
        if(spDispatchSchemes == null){
            emptyResultData.put("firstShipLoadingTime",new Date().getTime());
            return JsonResult.success(emptyResultData);
        }

        //获取年度计划方案详情信息
        List<SpDispatchPotentialSchemeDetail> details = spDispatchSchemeDetailService.getBaseMapper().selectList(
                new LambdaQueryWrapper<SpDispatchPotentialSchemeDetail>()
                .eq(SpDispatchPotentialSchemeDetail::getSchemeId,spDispatchSchemes.getId())
                .ne(SpDispatchPotentialSchemeDetail::getExecuteStatus,4)
        );
        if(details.size() == 0){
            emptyResultData.put("firstShipLoadingTime",new Date().getTime());
            return JsonResult.success(emptyResultData);
        }
        details = details.stream().sorted(Comparator.comparing(SpDispatchPotentialSchemeDetail::getSchemeNumber)).collect(Collectors.toList());
        BigDecimal tradingProfit = BigDecimal.ZERO;
        int unoccupiedDays = 0;
        Calendar calendar = Calendar.getInstance();


        BigDecimal yearInRentDays = BigDecimal.ZERO;
        BigDecimal yearInRentMoney = BigDecimal.ZERO;
        BigDecimal yearOutRentDays = BigDecimal.ZERO;
        BigDecimal yearOutRentMoney = BigDecimal.ZERO;
        BigDecimal shipDays = BigDecimal.ZERO;
        for (SpInformation spInformation : spInformations) {
            ShipRentYearInfoBO yearInfoBO = CommonUtil.getShipYearTradeInfo(spInformation,LocalDate.now().getYear());
            yearInRentDays = yearInRentDays.add(yearInfoBO.getYearInRentDays());
            yearInRentMoney = yearInRentMoney.add(yearInfoBO.getYearInRentMoney());
            yearOutRentDays = yearOutRentDays.add(yearInfoBO.getYearOutRentDays());
            yearOutRentMoney = yearOutRentMoney.add(yearInfoBO.getYearOutRentMoney());
        }
        List<String> shipNames = new LinkedList<>();
        List<String> dayList = new LinkedList<>();
        for (int i = 0; i < details.size(); i++) {
            SpDispatchPotentialSchemeDetail detail = details.get(i);
            if(detail.getExpectedLoadingPortId() != null){
                List<String> portIds = new LinkedList<>();
                portIds.add(String.valueOf(detail.getExpectedLoadingPortId()));
                detail.setExpectedLoadingPorts(portIds);
            }
            if(detail.getExpectedUnloadingPortId() != null){
                List<String> portIds = new LinkedList<>();
                portIds.add(String.valueOf(detail.getExpectedUnloadingPortId()));
                detail.setExpectedUnloadingPorts(portIds);
            }
            calendar.setTime(detail.getExpectedLoadingDate());
            if(calendar.get(Calendar.YEAR) == LocalDate.now().getYear()){
                //调度优化贸易相关数据只显示当前年份的
                if(detail.getTradingProfit() != null){
                    tradingProfit = tradingProfit.add(detail.getTradingProfit());
                }
                if(detail.getFobRestockProfit() != null){
                    tradingProfit = tradingProfit.add(detail.getFobRestockProfit());
                }
                if(detail.getDesRestockProfit() != null){
                    tradingProfit = tradingProfit.add(detail.getDesRestockProfit());
                }
                if(detail.getExpectedFullLoadVoyageDays() != null){
                    shipDays = shipDays.add(new BigDecimal(String.valueOf(detail.getExpectedFullLoadVoyageDays())));
                }
                if(detail.getExpectedEmptyLoadVoyageDays() != null){
                    shipDays = shipDays.add(new BigDecimal(String.valueOf(detail.getExpectedEmptyLoadVoyageDays())));
                }
                if(detail.getBackDays() != null && detail.getBackDays() > 30){
                    unoccupiedDays = (unoccupiedDays + detail.getBackDays());
                }
                if(!dayList.contains(detail.getShipName())){
                    if(detail.getFrontDays() != null && detail.getFrontDays() > 30){
                        unoccupiedDays = (unoccupiedDays + detail.getFrontDays());
                    }
                    dayList.add(detail.getShipName());
                }
                if(detail.getShipUseRate() != null){
                    shipUseRate = shipUseRate.add(detail.getShipUseRate());
                }
                if(!shipNames.contains(detail.getShipName()) && detail.getDispatchCost() != null){
                    dispatchCost = dispatchCost.add(detail.getDispatchCost());
                    shipNames.add(detail.getShipName());
                }
            }
        }

        //未下发的数据列表
        List<SpDispatchPotentialSchemeDetail> unSendList = details.stream().filter(detail -> detail.getExecuteStatus() == 0).collect(Collectors.toList());

        JSONObject resultData = new JSONObject();

        // 获取甘特图时间轴的开始时间（未下发的第一船货的装载时间）
        if(unSendList.size() > 0){
            SpDispatchPotentialSchemeDetail detailFirst = unSendList.stream().min(Comparator.comparing((SpDispatchPotentialSchemeDetail::getExpectedEmptyReturnWindow))).get();
            resultData.put("firstShipLoadingTime", DateUtil.offsetMonth(detailFirst.getExpectedLoadingDate(),-2).getTime());
        }else{
            //全部都下发了则以当前时间
            resultData.put("firstShipLoadingTime",new Date().getTime());
        }

        //船舶排布
        Map<String,List<SpDispatchPotentialSchemeDetail>> boatMap = details.stream().collect(Collectors.groupingBy(SpDispatchPotentialSchemeDetail::getShipName));
        JSONArray boatsArray = new JSONArray();
        for (SpInformation spInformation : spInformations) {
            String boatName = spInformation.getNameOfVessel();
            JSONObject boatDetailJson = new JSONObject();
            if(boatMap.get(boatName) == null && boatName.indexOf("虚拟") > -1){
                continue;
            }
            boatDetailJson.put("imo",spInformation.getImo());
            boatDetailJson.put("storageCapacity",spInformation.getStorageCapacity());
            boatDetailJson.put("storageCapacityMmbtu",spInformation.getStorageCapacityMmbtu());
            boatDetailJson.put("rentTimeSlot",JSONArray.parseArray(spInformation.getRentTimeSlot()));
            boatDetailJson.put("shipName",boatName);
            boatDetailJson.put("details",boatMap.get(boatName) != null ? boatMap.get(boatName) : new LinkedList<>());
            boatsArray.add(boatDetailJson);
        }
        resultData.put("shipNames",boatsArray);

        //资源排布
        Map<String,List<SpDispatchPotentialSchemeDetail>> goodsMap = details.stream().collect(Collectors.groupingBy(SpDispatchPotentialSchemeDetail::getGoodsNum));
        List<JSONObject> goodsArray = new LinkedList<>();
        for (String goodsName : goodsMap.keySet()) {
            JSONObject goodsDetailJson = new JSONObject();
            goodsDetailJson.put("goodsName",goodsName);
            goodsDetailJson.put("number",goodsMap.get(goodsName).get(0).getSchemeNumber());
            goodsDetailJson.put("details",goodsMap.get(goodsName));
            goodsArray.add(goodsDetailJson);
        }
        goodsArray = goodsArray.stream().sorted(
                Comparator.comparingInt(a -> ((JSONObject)a).getIntValue("number"))).collect(Collectors.toList());
        resultData.put("goodsNames",goodsArray);
        //资源方排布
        Map<String,List<SpDispatchPotentialSchemeDetail>> sourceSideMap = details.stream().collect(Collectors.groupingBy(SpDispatchPotentialSchemeDetail::getSeller));
        JSONArray sourceSideArray = new JSONArray();
        for (String sourceSideName : sourceSideMap.keySet()) {
            JSONObject sourceSideDetailJson = new JSONObject();
            sourceSideDetailJson.put("sellerName",sourceSideName);
            sourceSideDetailJson.put("details",sourceSideMap.get(sourceSideName));
            sourceSideArray.add(sourceSideDetailJson);
        }
        //船舶利用率=（总的航行天数（空载+满载）+租出的天数）/年度租入天数
        shipDays = shipDays.add(yearOutRentDays);

        shipUseRate = shipDays.multiply(new BigDecimal("100")).divide(yearInRentDays, 2, RoundingMode.HALF_UP);

        resultData.put("shipUseRate",shipUseRate);
        resultData.put("dispatchCost",dispatchCost);
        resultData.put("sellerNames",sourceSideArray);
        resultData.put("planId",spDispatchSchemes.getPlanId());
        resultData.put("schemeId",spDispatchSchemes.getId());
        resultData.put("isDistribute",spDispatchSchemes.getIsDistribute());
        resultData.put("tradingProfit",tradingProfit.subtract(dispatchCost));
        resultData.put("unoccupiedDays",unoccupiedDays);
        return JsonResult.success(resultData);
    }

    /**
     * 获取贸易利润率及空挡天数（保存、共享、发布）
     * @param schemeDetail
     * @param shipInfo
     */
    private void getDispatchIntervalDaysAndTradeRate(SpDispatchPotentialSchemeDetail schemeDetail
            ,SpInformation shipInfo){
        if(schemeDetail.getResourceContract() == null){
            return;
        }
        ConResourceMemorandum memorandum = resourceMemorandumMapper.getById(schemeDetail.getResourceContract());
        if(memorandum == null){
            return;
        }
        if(memorandum.getContractPrice() == null){
            schemeDetail.setTradingProfit(BigDecimal.ZERO);
            return;
        }
        //实际交付量 = 预计装载量-预计装载量*（时间差天数）*蒸发率-留底量
        BigDecimal realityUnload = schemeDetail.getSingleGoodsQuantity();
        if(shipInfo.getIsVirtual().intValue() == 1){
            shipInfo.setEvaporationRate(new BigDecimal("0.1"));
        }
        BigDecimal subDec = BigDecimal.ZERO;
        if(shipInfo.getEvaporationRate() != null){
            subDec = schemeDetail.getSingleGoodsQuantity().multiply(shipInfo.getEvaporationRate()).divide(new BigDecimal("100"));
        }
//        if(shipInfo.getRedeliveryStatus() != null){
//            subDec = subDec.add(shipInfo.getRedeliveryStatus());
//        }
        realityUnload = schemeDetail.getSingleGoodsQuantity().subtract(subDec);
        schemeDetail.setRealityUnloadingCapacity(realityUnload);
        //实际交付价格 = 合同价格
        if(memorandum != null && memorandum.getContractPrice() != null){
            schemeDetail.setConPrice(memorandum.getContractPrice());
        }else{
            schemeDetail.setConPrice(BigDecimal.ZERO);
        }

        /**
         * 年度计划默认都是回国，根据贸易利润为0来推算国内销售价格
         * 回国：贸易利润 = 实际交付量（预计卸载量）*实际交付价格（实际销售的价格）
         * +其他收入（为0）-其他交付成本（为0）-实际装载量（预计装载量）*实际结算单价（长协合同里面的合同价格）-其他费用（为0）
         */
        BigDecimal tradingProfit = BigDecimal.ZERO;
        schemeDetail.setTradingProfit(tradingProfit);

        BigDecimal sellPrice = BigDecimal.ZERO;
        if(schemeDetail.getConPrice().compareTo(BigDecimal.ZERO) > 0){
            sellPrice = (schemeDetail.getSingleGoodsQuantity().multiply(schemeDetail.getConPrice()))
                    .divide(schemeDetail.getRealityUnloadingCapacity(),2, RoundingMode.HALF_UP);
        }
        schemeDetail.setSellPrice(sellPrice);
    }

    @Override
    public JsonResult getSchemeHistory(HistoryDispatchBO historyDispatchBO) {
        List<SpDispatchPotentialScheme> planSchemes = new LinkedList<>();
        planSchemes = this.baseMapper.selectList(
                new LambdaQueryWrapper<SpDispatchPotentialScheme>()
                        .eq(StringUtils.isBlank(historyDispatchBO.getCreateBy()),SpDispatchPotentialScheme::getIsHistory,1)
                        .eq(StringUtils.isBlank(historyDispatchBO.getCreateBy()),SpDispatchPotentialScheme::getIsShare,1)
                        .eq(StringUtils.isNoneBlank(historyDispatchBO.getCreateBy()),SpDispatchPotentialScheme::getCreateBy, SecurityUtils.getUsername())
                        .eq(StringUtils.isNoneBlank(historyDispatchBO.getCreateBy()),SpDispatchPotentialScheme::getIsShare,"0")
                        .orderByDesc(SpDispatchPotentialScheme::getCreateDate)
        );

        if(planSchemes.size() == 0){
            return JsonResult.success(planSchemes);
        }
        //获取船舶信息
        List<SpInformation> spInformations = spInformationService.getAllSpInformationUsed(null);
        List<JSONObject> resultList = new LinkedList<>();
        BigDecimal yearInRentDays = BigDecimal.ZERO;
        BigDecimal yearInRentMoney = BigDecimal.ZERO;
        BigDecimal yearOutRentDays = BigDecimal.ZERO;
        BigDecimal yearOutRentMoney = BigDecimal.ZERO;
        for (SpInformation spInformation : spInformations) {
            ShipRentYearInfoBO yearInfoBO = CommonUtil.getShipYearTradeInfo(spInformation,LocalDate.now().getYear());
            yearInRentDays = yearInRentDays.add(yearInfoBO.getYearInRentDays());
            yearInRentMoney = yearInRentMoney.add(yearInfoBO.getYearInRentMoney());
            yearOutRentDays = yearOutRentDays.add(yearInfoBO.getYearOutRentDays());
            yearOutRentMoney = yearOutRentMoney.add(yearInfoBO.getYearOutRentMoney());
        }
        for (SpDispatchPotentialScheme spDispatchScheme : planSchemes) {
            //获取年度计划方案详情信息
            List<SpDispatchPotentialSchemeDetail> details = spDispatchSchemeDetailService.getBaseMapper().selectList(
                    new LambdaQueryWrapper<SpDispatchPotentialSchemeDetail>()
                            .eq(SpDispatchPotentialSchemeDetail::getSchemeId,spDispatchScheme.getId())
            );
            if(details.size() == 0){
                continue;
            }
            JSONObject resultData = new JSONObject();
            SpArrangeDataVo spArrangeDataVo = getSchemeUseRate(details);
            resultData.put("spArrangeDataVo",spArrangeDataVo);

            // 获取第一艘船装载时间和卸载时间
            SpDispatchPotentialSchemeDetail detailFirst = details.stream().min(Comparator.comparing((SpDispatchPotentialSchemeDetail::getExpectedEmptyReturnWindow))).get();
            resultData.put("firstShipLoadingTime",detailFirst.getExpectedLoadingDate().getTime());

            resultData.put("schemeInfo",spDispatchScheme);
            //船舶排布
            Map<String,List<SpDispatchPotentialSchemeDetail>> boatMap = details.stream().collect(Collectors.groupingBy(SpDispatchPotentialSchemeDetail::getShipName));
            JSONArray boatsArray = new JSONArray();
            BigDecimal shipDays = BigDecimal.ZERO;
            BigDecimal tradingProfit = BigDecimal.ZERO;
            BigDecimal shipUseRate = BigDecimal.ZERO;
            BigDecimal dispatchCost = BigDecimal.ZERO;
            int unoccupiedDays = 0;
            Calendar calendar = Calendar.getInstance();
            if(spInformations.size() > 0){
                for (SpInformation spInformation : spInformations) {
                    String boatName = spInformation.getNameOfVessel();
                    if(boatMap.get(boatName) == null){
                        if(boatName.indexOf("虚拟") > -1){
                            continue;
                        }
                    }else{
                        List<SpDispatchPotentialSchemeDetail> detailList = boatMap.get(boatName);
                        if(detailList.size() > 0 && detailList.get(0).getDispatchCost() != null){
                            dispatchCost = dispatchCost.add(detailList.get(0).getDispatchCost());
                        }
                        for (int i = 0; i < detailList.size(); i++) {
                            SpDispatchPotentialSchemeDetail spDispatchSchemeDetail = detailList.get(i);
                            calendar.setTime(spDispatchSchemeDetail.getExpectedLoadingDate());
                            if(calendar.get(Calendar.YEAR) == LocalDate.now().getYear()){
                                if(spDispatchSchemeDetail.getExpectedFullLoadVoyageDays() != null){
                                    shipDays = shipDays.add(new BigDecimal(String.valueOf(spDispatchSchemeDetail.getExpectedFullLoadVoyageDays())));
                                }
                                if(spDispatchSchemeDetail.getExpectedEmptyLoadVoyageDays() != null){
                                    shipDays = shipDays.add(new BigDecimal(String.valueOf(spDispatchSchemeDetail.getExpectedEmptyLoadVoyageDays())));
                                }
                            }
                            if(spDispatchSchemeDetail.getTradingProfit() != null){
                                tradingProfit = tradingProfit.add(spDispatchSchemeDetail.getTradingProfit());
                            }
                            if(spDispatchSchemeDetail.getFrontDays() != null && spDispatchSchemeDetail.getFrontDays() > 30){
                                unoccupiedDays = (unoccupiedDays + spDispatchSchemeDetail.getFrontDays());
                            }
                            if(i == (detailList.size() - 1)){
                                if(spDispatchSchemeDetail.getBackDays() != null && spDispatchSchemeDetail.getBackDays() > 30){
                                    unoccupiedDays = (unoccupiedDays + spDispatchSchemeDetail.getBackDays());
                                }
                            }
                            if(spDispatchSchemeDetail.getShipUseRate() != null){
                                shipUseRate = shipUseRate.add(spDispatchSchemeDetail.getShipUseRate());
                            }
                        }
                    }
                    JSONObject boatDetailJson = new JSONObject();
                    boatDetailJson.put("rentTimeSlot",JSONArray.parseArray(spInformation.getRentTimeSlot()));
                    boatDetailJson.put("shipName",boatName);
                    boatDetailJson.put("details",boatMap.get(boatName) != null ? boatMap.get(boatName) : new LinkedList<>());
                    boatsArray.add(boatDetailJson);
                }
            }else{
                for (String boatName : boatMap.keySet()) {
                    if(boatMap.get(boatName) == null){
                        if(boatName.indexOf("虚拟") > -1){
                            continue;
                        }
                    }else{
                        List<SpDispatchPotentialSchemeDetail> detailList = boatMap.get(boatName);
                        if(detailList.size() > 0 && detailList.get(0).getDispatchCost() != null){
                            dispatchCost = dispatchCost.add(detailList.get(0).getDispatchCost());
                        }
                        for (int i = 0; i < detailList.size(); i++) {
                            SpDispatchPotentialSchemeDetail spDispatchSchemeDetail = detailList.get(i);
                            calendar.setTime(spDispatchSchemeDetail.getExpectedLoadingDate());
                            if(calendar.get(Calendar.YEAR) == LocalDate.now().getYear()){
                                if(spDispatchSchemeDetail.getExpectedFullLoadVoyageDays() != null){
                                    shipDays = shipDays.add(new BigDecimal(String.valueOf(spDispatchSchemeDetail.getExpectedFullLoadVoyageDays())));
                                }
                                if(spDispatchSchemeDetail.getExpectedEmptyLoadVoyageDays() != null){
                                    shipDays = shipDays.add(new BigDecimal(String.valueOf(spDispatchSchemeDetail.getExpectedEmptyLoadVoyageDays())));
                                }
                            }
                            if(spDispatchSchemeDetail.getTradingProfit() != null){
                                tradingProfit = tradingProfit.add(spDispatchSchemeDetail.getTradingProfit());
                            }
                            if(spDispatchSchemeDetail.getFrontDays() != null && spDispatchSchemeDetail.getFrontDays() > 30){
                                unoccupiedDays = (unoccupiedDays + spDispatchSchemeDetail.getFrontDays());
                            }
                            if(i == (detailList.size() - 1)){
                                if(spDispatchSchemeDetail.getBackDays() != null && spDispatchSchemeDetail.getBackDays() > 30){
                                    unoccupiedDays = (unoccupiedDays + spDispatchSchemeDetail.getBackDays());
                                }
                            }
                            if(spDispatchSchemeDetail.getShipUseRate() != null){
                                shipUseRate = shipUseRate.add(spDispatchSchemeDetail.getShipUseRate());
                            }
                        }
                    }
                    JSONObject boatDetailJson = new JSONObject();
                    boatDetailJson.put("shipName",boatName);
                    boatDetailJson.put("details",boatMap.get(boatName) != null ? boatMap.get(boatName) : new LinkedList<>());
                    boatsArray.add(boatDetailJson);
                }
            }
            //船舶利用率=（总的航行天数（空载+满载）+租出的天数）/年度租入天数
            shipDays = shipDays.add(yearOutRentDays);

            shipUseRate = shipDays.multiply(new BigDecimal("100")).divide(yearInRentDays, 2, RoundingMode.HALF_UP);

            resultData.put("shipUseRate",shipUseRate);
            resultData.put("dispatchCost",dispatchCost);
            resultData.put("tradingProfit",tradingProfit.subtract(dispatchCost));
            resultData.put("unoccupiedDays",unoccupiedDays);
            resultData.put("shipNames",boatsArray);

            //资源排布
            Map<String,List<SpDispatchPotentialSchemeDetail>> goodsMap = details.stream().collect(Collectors.groupingBy(SpDispatchPotentialSchemeDetail::getGoodsNum));
            JSONArray goodsArray = new JSONArray();
            for (String goodsName : goodsMap.keySet()) {
                JSONObject goodsDetailJson = new JSONObject();
                goodsDetailJson.put("goodsName",goodsName);
                goodsDetailJson.put("details",goodsMap.get(goodsName));
                goodsArray.add(goodsDetailJson);
            }
            resultData.put("goodsNames",goodsArray);
            //资源方排布
            Map<String,List<SpDispatchPotentialSchemeDetail>> sourceSideMap = details.stream().collect(Collectors.groupingBy(SpDispatchPotentialSchemeDetail::getSeller));
            JSONArray sourceSideArray = new JSONArray();
            for (String sourceSideName : sourceSideMap.keySet()) {
                JSONObject sourceSideDetailJson = new JSONObject();
                List<SpDispatchPotentialSchemeDetail> detailList = sourceSideMap.get(sourceSideName);
                sourceSideDetailJson.put("sellerName",sourceSideName);
                sourceSideDetailJson.put("details",detailList);
                sourceSideArray.add(sourceSideDetailJson);
            }
            resultData.put("sellerNames",sourceSideArray);
            resultData.put("schemeId",spDispatchScheme.getId());
            resultList.add(resultData);
        }

        return JsonResult.success(resultList);
    }

    /**
     * 根据方案详情获取方案使用情况数值
     * @param details
     * @return
     */
    public SpArrangeDataVo getSchemeUseRate(List<SpDispatchPotentialSchemeDetail> details){
        SpArrangeDataVo spArrangeDataVo = new SpArrangeDataVo();
        //航行天数
        long travelDays = 0L;
        //总航行天数
        long allTravelDays = 0L;
        //运费
        BigDecimal freight = BigDecimal.ZERO;
        for (SpDispatchPotentialSchemeDetail detail : details) {
            if(detail.getExpectedLoadingDate() != null && detail.getExpectedUnloadingWindow() != null){
                travelDays = (travelDays + com.ship.common.core.utils.DateUtil.getDateDays(detail.getExpectedLoadingDate(),detail.getExpectedUnloadingWindow(),1));
            }
            if(detail.getExpectedLoadingDate() != null && detail.getExpectedEmptyReturnWindow() != null){
                allTravelDays = (allTravelDays + com.ship.common.core.utils.DateUtil.getDateDays(detail.getExpectedLoadingDate(),detail.getExpectedEmptyReturnWindow(),1));
            }
            if(detail.getFreight() != null){
                freight = freight.add(detail.getFreight());
            }
        }
        spArrangeDataVo.setFreight(freight);
        spArrangeDataVo.setTravelDays(travelDays);

        int year = details.get(0).getPlanYear();
        //获取当前年度所有船只总的租期（天），来计算整个方案船队的利用率
        List<ConShipping> shippings = conShippingService.getBaseMapper().selectList(
                new LambdaQueryWrapper<ConShipping>()
                        .last("where YEAR(starting_date_of_lease_begin) <= "+year+" AND YEAR(starting_date_of_lease_end) >= "+year)
        );
        if(shippings.size() == 0){
            return spArrangeDataVo;
        }
        Date startDate = com.ship.common.core.utils.DateUtil.String2Date(year+"-01-01 00:00:00", "yyyy-MM-dd");
        Date endDate = com.ship.common.core.utils.DateUtil.String2Date(year+"-12-31 23:59:59", "yyyy-MM-dd");
        long leaseDays = 0L;
        for (ConShipping shipping : shippings) {
            Date leaseStart = shipping.getDeliveryDateBegin().before(startDate) ? startDate : shipping.getDeliveryDateBegin();
            Date leaseEnd = shipping.getStartingDateOfLeaseEnd().after(endDate) ? endDate : shipping.getStartingDateOfLeaseEnd();
            leaseDays = (leaseDays + com.ship.common.core.utils.DateUtil.getDateDays(leaseStart,leaseEnd,1));
        }
        BigDecimal useRate = new BigDecimal(String.valueOf(allTravelDays))
                .divide(new BigDecimal(String.valueOf(leaseDays)),2,BigDecimal.ROUND_UP);
        spArrangeDataVo.setShipUseRate(useRate.multiply(new BigDecimal("100")));
        return spArrangeDataVo;
    }

    @Override
    public JsonResult schemeRollback(String schemeId) {
        //获取要还原的方案数据
        SpDispatchPotentialScheme spDispatchScheme = this.baseMapper.selectById(schemeId);
        if(spDispatchScheme == null){
            return JsonResult.failed("方案信息异常");
        }
        //获取方案对应的详情信息
        List<SpDispatchPotentialSchemeDetail> details = spDispatchSchemeDetailService.getBaseMapper().selectList(
                new LambdaQueryWrapper<SpDispatchPotentialSchemeDetail>()
                        .eq(SpDispatchPotentialSchemeDetail::getSchemeId,spDispatchScheme.getId())
        );
        if(details.size() == 0){
            return JsonResult.failed("方案详细信息异常");
        }

        SpDispatchPotentialScheme updateData = new SpDispatchPotentialScheme();
        updateData.setIsHistory(1);
        this.update(updateData,new LambdaQueryWrapper<>());

        //新增一条方案信息
        spDispatchScheme.setId(null);
        spDispatchScheme.setIsHistory(0);
        spDispatchScheme.setIsShare(0);
        spDispatchScheme.setApproveStatus(1);
        spDispatchScheme.setCreateDate(new Date());
        spDispatchScheme.setCreateBy(SecurityUtils.getUsername());
        this.baseMapper.insert(spDispatchScheme);

        //保存方案详情信息
        for (SpDispatchPotentialSchemeDetail detail : details) {
            detail.setSchemeId(spDispatchScheme.getId());
            detail.setCreateDate(new Date());
            detail.setCreateBy(SecurityUtils.getUsername());
            detail.setId(null);
        }
        spDispatchSchemeDetailService.saveBatch(details);

        return JsonResult.success();
    }

    @Override
    public JsonResult<List<SpDispatchPotentialSchemeDetail>> getSchemeDetailHistory(SchemeChartSimpleDto dto) {
        if(dto.getSchemeDetailId() == null){
            return JsonResult.failed("方案详情ID不能为空！");
        }
        List<SpDispatchPotentialSchemeDetail> resultList = this.baseMapper.getSchemeDetailHistory(dto);
        if(resultList.size() == 0){
            SpDispatchPotentialSchemeDetail detail = spDispatchSchemeDetailService.getBaseMapper().selectById(dto.getSchemeDetailId());
            if(detail != null){
                if(detail.getExpectedLoadingPortId() != null){
                    List<String> portIds = new LinkedList<>();
                    portIds.add(String.valueOf(detail.getExpectedLoadingPortId()));
                    detail.setExpectedLoadingPorts(portIds);
                }
                if(detail.getExpectedUnloadingPortId() != null){
                    List<String> portIds = new LinkedList<>();
                    portIds.add(String.valueOf(detail.getExpectedUnloadingPortId()));
                    detail.setExpectedUnloadingPorts(portIds);
                }
                resultList.add(detail);
            }
        }
        return JsonResult.success(resultList);
    }

    @Override
    public JsonResult<Object> getSchemeDetailPage(SpDispatchPotentialSchemeDetail dto) {
        //获取最新的方案信息
        SpDispatchPotentialScheme spDispatchScheme = this.baseMapper.selectOne(
                new LambdaQueryWrapper<SpDispatchPotentialScheme>()
                        .eq(SpDispatchPotentialScheme::getIsHistory,0)
                        .eq(dto.getSchemeId() != null,SpDispatchPotentialScheme::getId,dto.getSchemeId())
                        .and(qw -> {
                            qw.eq(SpDispatchPotentialScheme::getCreateBy,SecurityUtils.getUsername());
                            qw.or().eq(SpDispatchPotentialScheme::getIsShare,1);
                        })
                        .orderByDesc(SpDispatchPotentialScheme::getCreateDate)
                        .last("limit 1")
        );
        if(spDispatchScheme == null){
            return JsonResult.success(new Page<>());
        }
        dto.setSchemeId(spDispatchScheme.getId());
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("scheme_id",spDispatchScheme.getId());
        queryWrapper.orderByDesc("expected_loading_date");
        Page<SpDispatchPotentialSchemeDetail> resultPage = spDispatchSchemeDetailService.page(dto,queryWrapper);
        for (SpDispatchPotentialSchemeDetail detail : resultPage.getList()) {
            if(detail.getLoadingCapacity() != null){
                detail.setLoadingCapacityString(NumberFormatUtil.numericFormatting(detail.getLoadingCapacity())+" m³");
            }
            if(detail.getSingleGoodsQuantity() != null){
                detail.setSingleGoodsQuantityString(NumberFormatUtil.numericFormatting(detail.getSingleGoodsQuantity())+" MMBtu");
            }
            if(detail.getOilConsumption() != null){
                detail.setOilConsumptionString(NumberFormatUtil.numericFormatting(detail.getOilConsumption()));
            }
            if(detail.getExpectedLoadingPortId() != null){
                List<String> portIds = new LinkedList<>();
                portIds.add(String.valueOf(detail.getExpectedLoadingPortId()));
                detail.setExpectedLoadingPorts(portIds);
            }
            if(detail.getExpectedUnloadingPortId() != null){
                List<String> portIds = new LinkedList<>();
                portIds.add(String.valueOf(detail.getExpectedUnloadingPortId()));
                detail.setExpectedUnloadingPorts(portIds);
            }
        }
        return JsonResult.success(resultPage);
    }

    @Override
    public String exportDispatchPlanAndGante(SpDispatchSchemeDetailExVo spDispatchSchemeDetailExVo,String fileUrl) {
        String CsoldPart = "http://10.75.34.224:9300/statics";
        String ZsoldPart = "http://10.75.33.149:9300/statics";
        String CsPart = "https://lngshippingcs.cgp.cnooc/api/file/statics";
        String ZsPart = "https://lngshipping.cgp.cnooc/api/file/statics";

        // 获取当前日期
        LocalDateTime currentDate = LocalDateTime.now();
        // 格式化日期为指定格式（例如：年月日）
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH.mm");
        String formattedDate = currentDate.format(formatter);

        String zipFilename = "调度优化-"+formattedDate+".zip";
        String filename = "调度优化-"+formattedDate+".xlsx";

        String newUrl = "";
        if (fileUrl.contains("https://lngshipping.cgp.cnooc")) {
            newUrl = fileUrl.replace(ZsPart, ZsoldPart);
        }else if (fileUrl.contains("https://lngshippingcs.cgp.cnooc")){
            newUrl = fileUrl.replace(CsPart, CsoldPart);
        }else {
            newUrl = fileUrl;
        }
        try {
            URL url = new URL(newUrl);
            URLConnection conn = url.openConnection();
            InputStream inputStream = conn.getInputStream();

            try (FileOutputStream outputStream = new FileOutputStream(filename)) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            }
        }catch (IOException e) {
            // 处理工作簿创建异常
            e.printStackTrace();
        }


            // 从 SpYearPlanSchemeDetailExportVo 中获取图片链接
            PictureUrl pictureUrl = spDispatchSchemeDetailExVo.getPictureUrl();
            String shipUrl = pictureUrl.getShipUrl();
            String goodsUrl = pictureUrl.getGoodsUrl();

            // 下载图片并保存到本地
            saveBase64Image(shipUrl, "船舶排布.jpg");
            saveBase64Image(goodsUrl, "货源排布.jpg");

            // 创建一个压缩包并添加这些图片文件
            createZipFile(zipFilename, filename,"船舶排布.jpg", "货源排布.jpg");

            //文件地址
            File file = new File(zipFilename);
            try {
            FileInputStream input = new FileInputStream(file);
            MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "application/octet-stream", input);
            R<SysFile> result1 = remoteFileService.upload(multipartFile);
            if(result1.getCode() != R.SUCCESS){
                throw new BusException("文件服务器连接失败", BaseResultCode.GENERAL_ERROR);
            }
            String url = result1.getData().getHttpsUrl();

            File zipFile = new File(zipFilename);
            File excelFile = new File(filename);
            File picture1 = new File("船舶排布.jpg");
            File picture2 = new File("货源排布.jpg");
            if (zipFile.exists()) {
                if (zipFile.delete()) {
                    excelFile.delete();
                    picture1.delete();
                    picture2.delete();
                }
            }

            return url;
        } catch (IOException e) {
            // 处理工作簿创建异常
            e.printStackTrace();
            return "创建 Excel 工作簿失败";
        }
    }

    public void createZipFile(String zipFileName, String... filesToAdd) {
        try {
            FileOutputStream fos = new FileOutputStream(zipFileName);
            ZipOutputStream zos = new ZipOutputStream(fos);

            for (String fileToAdd : filesToAdd) {
                addToZipFile(fileToAdd, zos);
            }

            zos.close();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            // 处理文件未找到异常
        } catch (IOException e) {
            e.printStackTrace();
            // 处理其他 IO 异常
        }
    }

    private void addToZipFile(String fileName, ZipOutputStream zos) throws IOException {
        File file = new File(fileName);
        FileInputStream fis = new FileInputStream(file);

        ZipEntry zipEntry = new ZipEntry(fileName);
        zos.putNextEntry(zipEntry);

        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zos.write(bytes, 0, length);
        }

        zos.closeEntry();
        fis.close();
    }

    @Override
    public void saveBase64Image(String base64Data, String fileName) {
        // 移除数据开头的描述信息，获取实际的 Base64 编码数据
        String[] parts = base64Data.split(",");
        String base64Image = parts.length > 1 ? parts[1] : base64Data;

        // 将 Base64 数据解码为字节数组
        byte[] decodedBytes = Base64.getDecoder().decode(base64Image);

        // 保存解码后的字节数组为图片文件
        try (OutputStream outputStream = new FileOutputStream(fileName)) {
            outputStream.write(decodedBytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public JsonResult<SpDispatchPotentialSchemeDetail> tradingProfitUpdate(SpDispatchPotentialSchemeDetail detail) {
        if(detail.getId() == null){
            return JsonResult.failed("id不能为空");
        }
        SpDispatchPotentialSchemeDetail schemeDetail = spDispatchSchemeDetailService.getById(detail.getId());
        if(schemeDetail == null){
            return JsonResult.failed("方案详情信息异常");
        }
        BeanCopyUtils.copy(detail,schemeDetail);
        BigDecimal defUnitValue = new BigDecimal("10000");
        //预计采购成本 计划装载量*预计采购单价
        schemeDetail.setConPriceCost(schemeDetail.getConPrice().multiply(schemeDetail.getSingleGoodsQuantity()).divide(defUnitValue,2,RoundingMode.UP));
        //实际采购成本 实际装载量*实际采购单价
        BigDecimal realityConPriceCost = schemeDetail.getRealityConPrice().multiply(schemeDetail.getSingleGoodsQuantity());
        schemeDetail.setRealityConPriceCost(realityConPriceCost.divide(defUnitValue,2,RoundingMode.UP));
        //实际总装载成本=运河费（装载）+港口费（装载）+其他费用（装载）+实际采购成本
        schemeDetail.setRealityLoadTotalCost((realityConPriceCost.add(schemeDetail.getLoadPassCost())
                .add(schemeDetail.getLoadPortCost()).add(schemeDetail.getLoadOtherCost())).divide(defUnitValue,2,RoundingMode.UP));

        //预计销售收入
        schemeDetail.setExpectSellMoney(schemeDetail.getSellPrice().multiply(schemeDetail.getExpectedUnloadGoodsQuantity()).divide(defUnitValue,2,RoundingMode.UP));
        //实际销售收入
        BigDecimal realitySellMoney = schemeDetail.getRealitySellPrice().multiply(schemeDetail.getRealityUnloadingCapacity());
        schemeDetail.setRealitySellMoney(realitySellMoney.divide(defUnitValue,2,RoundingMode.UP));

        //国际贸易利润=船舶优化成本+实际销售收入+其他收入-装载运河、港口、其他费用-卸载运河、港口、其他费用-实际采购成本  单位万美元
        schemeDetail.setNationalTradingProfit((realitySellMoney.add(schemeDetail.getOtherGetMoney()).subtract(schemeDetail.getLoadPassCost())
                .subtract(schemeDetail.getLoadPortCost()).subtract(schemeDetail.getLoadOtherCost())
                .subtract(schemeDetail.getUnloadPassCost()).subtract(schemeDetail.getUnloadPortCost())
                .subtract(schemeDetail.getUnloadOtherCost()).subtract(realityConPriceCost)).divide(defUnitValue,2,RoundingMode.UP));

        //实际总交付成本=运河费（卸载）+港口费（卸载）+其他费用（卸载)
        schemeDetail.setRealityTotalDeliverCost((schemeDetail.getUnloadPassCost()
                .add(schemeDetail.getUnloadPortCost()).add(schemeDetail.getUnloadOtherCost())).divide(defUnitValue,2,RoundingMode.UP));

        //获取船只租金租金信息
//        ASFDASD

        //贸易利润率=国际贸易利润+补货利润+船舶优化成本
        if(schemeDetail.getRestockProfit() == null){
            schemeDetail.setRestockProfit(BigDecimal.ZERO);
        }
        if(schemeDetail.getDispatchCost() == null){
            schemeDetail.setDispatchCost(BigDecimal.ZERO);
        }
        schemeDetail.setTradingProfit(schemeDetail.getNationalTradingProfit().add(schemeDetail.getRestockProfit()).add(schemeDetail.getDispatchCost()));
        spDispatchSchemeDetailService.updateById(schemeDetail);
        return JsonResult.success(schemeDetail);
    }

    @Override
    public JsonResult schemeSell(SchemeChartSellDto dto) {
        SpDispatchPotentialSchemeDetail schemeDetail = spDispatchSchemeDetailService.getById(dto.getSchemeDetailId());
        if(schemeDetail == null){
            return JsonResult.failed("方案信息异常！");
        }
        if(schemeDetail.getImo().indexOf("virtualShip") > -1){
            return JsonResult.failed("虚拟船不支持此操作！");
        }
        if(dto.getSaveType().intValue() == 1){
            //绑定销售合同
            if(dto.getSellConId() == null){
                return JsonResult.failed("销售合同ID不能为空！");
            }
            ConResourceMemorandum resourceMemorandum = resourceMemorandumMapper.getById(dto.getSellConId());
            if(resourceMemorandum == null){
                return JsonResult.failed("销售合同信息异常！");
            }
            if(resourceMemorandum.getContractPrice() == null){
                return JsonResult.success();
            }
            schemeDetail.setSellPrice(resourceMemorandum.getContractPrice());
            schemeDetail.setSellerResourceContract(resourceMemorandum.getId());
            schemeDetail.setSellerContractName(resourceMemorandum.getContractName());
            schemeDetail.setSellerTradeType(resourceMemorandum.getTradeType());
            schemeDetail.setSellerTradeBody(resourceMemorandum.getTradeBody());

            //贸易利润率=（销售价格*实际卸载量）-（实际装载量*合同价格）
            BigDecimal tradingProfit = BigDecimal.ZERO;
            if(schemeDetail.getSingleGoodsQuantity() != null && schemeDetail.getConPrice() != null && schemeDetail.getRealityUnloadingCapacity() != null){
                tradingProfit = schemeDetail.getSellPrice().multiply(schemeDetail.getRealityUnloadingCapacity())
                        .subtract(schemeDetail.getSingleGoodsQuantity().multiply(schemeDetail.getConPrice()));
            }
            tradingProfit = tradingProfit.divide(new BigDecimal("10000"),2,RoundingMode.HALF_UP);
            schemeDetail.setTradingProfit(tradingProfit);

        } else if(dto.getSaveType().intValue() == 2){
            //FOB补货
            if(dto.getFobSchemeDetailId() == null){
                return JsonResult.failed("补货的航次信息不能为空！");
            }
            SpDispatchPotentialSchemeDetail fobSchemeDetail = spDispatchSchemeDetailService.getById(dto.getFobSchemeDetailId());
            if(fobSchemeDetail == null){
                return JsonResult.failed("补货的航次信息异常！");
            }
            //补货利润=某航次卸载国内销售价格（实际交付价格）*预计卸载量（补货）-补货航次实际装载量*补货航次采购价格
            BigDecimal tradingProfit = BigDecimal.ZERO;
            if(schemeDetail.getSingleGoodsQuantity() != null && schemeDetail.getConPrice() != null && schemeDetail.getRealityUnloadingCapacity() != null){
                tradingProfit = schemeDetail.getSellPrice().multiply(fobSchemeDetail.getRealityUnloadingCapacity())
                        .subtract(fobSchemeDetail.getSingleGoodsQuantity().multiply(fobSchemeDetail.getConPrice()));
            }
            tradingProfit = tradingProfit.divide(new BigDecimal("10000"),2,RoundingMode.HALF_UP);
            schemeDetail.setFobRestockProfit(tradingProfit);
            schemeDetail.setFobVoyageNo(fobSchemeDetail.getVoyageNo());
            schemeDetail.setFobSchemeDetailId(fobSchemeDetail.getArrangeSchemeDetailId());
        } else if(dto.getSaveType().intValue() == 3){
            //DES补货
            if(dto.getDesGoodsPrice() == null || dto.getDesGoodsQuantity() == null){
                return JsonResult.failed("DES补货信息不能为空！");
            }
            if(dto.getDesQuantityUnit().intValue() == 2){
                //m³
                BigDecimal goodsQuantityNew = dto.getDesGoodsQuantity().multiply(BigDecimal.valueOf(0.985))
                        .subtract(BigDecimal.valueOf(500)).multiply(BigDecimal.valueOf(22.5))
                        .setScale(0, BigDecimal.ROUND_DOWN);
                dto.setDesGoodsQuantity(goodsQuantityNew);
            }
            if(dto.getDesQuantityUnit().intValue() == 3){
                //MT 1mt = 47.3684mmbtu
                BigDecimal goodsQuantityNew = dto.getDesGoodsQuantity().multiply(BigDecimal.valueOf(47.3684))
                        .setScale(0, BigDecimal.ROUND_DOWN);
                dto.setDesGoodsQuantity(goodsQuantityNew);
            }

            //进行货币转换（暂定默认美元）

            schemeDetail.setDesGoodsPrice(dto.getDesGoodsPrice());
            schemeDetail.setDesGoodsQuantity(dto.getDesGoodsQuantity());
            //补货利润=补货航次实际装载量*（某航次卸载国内销售价格-补货航次采购价格）
            BigDecimal tradingProfit = BigDecimal.ZERO;
            if(schemeDetail.getSellPrice() != null && schemeDetail.getDesGoodsPrice() != null && schemeDetail.getDesGoodsQuantity() != null){
                tradingProfit = (schemeDetail.getSellPrice().subtract(dto.getDesGoodsPrice()))
                        .multiply(dto.getDesGoodsQuantity());
            }
            tradingProfit = tradingProfit.divide(new BigDecimal("10000"),2,RoundingMode.HALF_UP);
            schemeDetail.setDesRestockProfit(tradingProfit);
        } else {
            return JsonResult.failed("未知的操作类型！");
        }
        spDispatchSchemeDetailService.updateById(schemeDetail);
        return JsonResult.success();
    }
}
